package com.marklogic.ps.servicetester.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;

import org.apache.batik.util.gui.xmleditor.XMLEditorKit;
import org.apache.commons.httpclient.HttpException;

import com.marklogic.ps.servicetester.domain.Query;
import com.marklogic.ps.servicetester.domain.ServerConnectionInfo;
import com.marklogic.ps.servicetester.domain.Service;
import com.marklogic.ps.servicetester.domain.ServiceTesterPreferences;
import com.marklogic.ps.servicetester.resources.Icons;
import com.marklogic.ps.servicetester.services.PreferencesServiceImpl;
import com.marklogic.ps.servicetester.services.ServiceHelper;
import com.marklogic.ps.servicetester.services.ServicesService;
import com.marklogic.ps.servicetester.services.ServicesServiceImpl;
import com.marklogic.ps.servicetester.util.XmlUtil;

public class QueryPanel extends JPanel {

	// private QueryController controller;
	private ServicesService servicesService;
	private ServiceHelper serviceHelper;
	
	//private JTextArea querySourceTextArea;
	private JEditorPane querySourceEditor;
	private JEditorPane queryResultEditor;
	private Query selectedQuery;
	
	private ServiceTesterPreferences preferences;
	
	private JComboBox serverCombo;
	
	PreferencesServiceImpl prefsService;
	
	private JFrame frame;
	
	public QueryPanel() {
	}

	public void init(JFrame frame) {
		this.frame = frame;
		prefsService = new PreferencesServiceImpl();
		preferences = prefsService.loadPreferences();
		
		querySourceEditor = new JEditorPane();
		querySourceEditor.setEditorKitForContentType(XMLEditorKit.XML_MIME_TYPE, new XMLEditorKit());
		querySourceEditor.setContentType(XMLEditorKit.XML_MIME_TYPE);
		
		queryResultEditor = new JEditorPane();
		queryResultEditor.setEditorKitForContentType(XMLEditorKit.XML_MIME_TYPE, new XMLEditorKit());
		queryResultEditor.setContentType(XMLEditorKit.XML_MIME_TYPE);
		
		JScrollPane scrollPane = new JScrollPane(querySourceEditor);

		JSplitPane rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
		rightSplitPane.setTopComponent(scrollPane);
		rightSplitPane.setBottomComponent(new JScrollPane(queryResultEditor));
		
		final JTree tree = new JTree();
		
		Collection c = preferences.getServerConnectionInfo();
		serverCombo = new JComboBox(c.toArray());
		//serverCombo.setEditable(true);
		serverCombo.addActionListener(new ActionListener () {
			public void actionPerformed(ActionEvent e) {
				ServerConnectionInfo sci = (ServerConnectionInfo)serverCombo.getSelectedItem();
				tree.setModel(getServicesModel());
				querySourceEditor.setText(null);
				queryResultEditor.setText(null);
			}
		});
		tree.setModel(getServicesModel());
		
		JRolloverButton connectionAddButton = new JRolloverButton(Icons.DATABASE_ADD, "Add Database Connection");
		ActionListener connectionSaveListner = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				ServerConnectionInfo i = (ServerConnectionInfo)e.getSource();
				serverCombo.addItem(i);
				serverCombo.setSelectedItem(i);
				
				preferences.addServerConnectionInfo(i);
				prefsService.savePreferences(preferences);
			}};
		final ServerConnectionDialog d = new ServerConnectionDialog(frame, connectionSaveListner);
		connectionAddButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				d.setVisible(true);
			}});
		
		JRolloverButton runQueryButton = new JRolloverButton(Icons.START, "Submit Query");
        runQueryButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				runQuery();
			}});
		JToolBar toolBar = new JToolBar();
		toolBar.add(connectionAddButton);
		toolBar.add(serverCombo);
        toolBar.add(runQueryButton);
        

		
		
        tree.setToggleClickCount(-1);
        tree.getSelectionModel().setSelectionMode(
                TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.setCellRenderer(new QueryTreeCellRenderer());

        // Listen for when the selection changes.
        tree.addMouseListener(new MouseAdapter() {

            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
                            .getLastSelectedPathComponent();
                    if (node != null && !node.isRoot()) {
                    	Object obj = node.getUserObject();
                    	if (obj instanceof Query) {
                    		Query query = (Query)obj;
                    		querySelected(query);
                    	}
                    }
                }
            }

        });
        JScrollPane treeScrollPane = new JScrollPane(tree);
		

		final JSplitPane splitPane = new JSplitPane(
				JSplitPane.HORIZONTAL_SPLIT, treeScrollPane, rightSplitPane);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(175);

		splitPane.setPreferredSize(new Dimension(800, 600));

		this.setLayout(new BorderLayout());
		this.add(toolBar, BorderLayout.NORTH);
		this.add(splitPane, BorderLayout.CENTER);
	}
	
//	private String getCurrentServerUri() {
//		ServerConnectionInfo sci = (ServerConnectionInfo)serverCombo.getSelectedItem();
//		String result = null;
//		if (sci != null) {
//			result = sci.getBaseUrl();
//		}
//		return result;
//	}
	
	private ServerConnectionInfo getCurrentServerConnectionInfo() {
		ServerConnectionInfo sci = (ServerConnectionInfo)serverCombo.getSelectedItem();
		return sci;
	}
	
	private void querySelected(Query query) {
		//System.out.println(query);
		queryResultEditor.setText(null);
		String request = query.getFormattedXml();
		if (request != null && request.length() > 0) {
			querySourceEditor.setText(request);
		} else {
			querySourceEditor.setText("No query request");
		}
		
		this.selectedQuery = query;
	}
	
	private void runQuery() {
		String queryText = querySourceEditor.getText();
		String result;
		try {
			ServiceHelper serviceHelper = new ServiceHelper(getCurrentServerConnectionInfo());
			result = serviceHelper.runQuery(selectedQuery, queryText);
			String formattedXml = "No results";
			if (result != null && result.length() > 0) {
				formattedXml = XmlUtil.formatXml(result);
			}
			queryResultEditor.setText(formattedXml);
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	public DefaultTreeModel getServicesModel() {
		DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Services");
		// rootOrg.setTreeNode(rootNode);
		DefaultTreeModel model = new DefaultTreeModel(rootNode);
		ServerConnectionInfo sci = getCurrentServerConnectionInfo();
		if (sci != null) {
			List<Service> services = null;
      try {
        services = servicesService.getServices(sci);
      } catch (Exception e) {
        JOptionPane.showMessageDialog(frame, e.getMessage(), "Error retrieving services", JOptionPane.ERROR_MESSAGE);
      }
      if (services != null) {
        for (Service service : services) {
          DefaultMutableTreeNode serviceNode = new DefaultMutableTreeNode(
              service);
          rootNode.add(serviceNode);
          List<Query> queries = service.getQueries();
          if (queries != null) {
            for (Query query : queries) {
              DefaultMutableTreeNode queryNode = new DefaultMutableTreeNode(query);
              serviceNode.add(queryNode);
            }
          }
        }  
      }
		}
		
		return model;
	}

	public static void main(String[] argv) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// QueryController controller = new QueryControllerImpl();
		
		JFrame frame = new JFrame("Service Tester");
		
		ServicesServiceImpl s = new ServicesServiceImpl();
		QueryPanel qp = new QueryPanel();
		qp.setServicesService(s);
//		//String baseUrl = "http://localhost:7005/";
//		//String baseUrl = "http://localhost:7004/";
//		qp.setBaseUrl(baseUrl);
		qp.init(frame);

		
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().add(qp);
		frame.pack();
		frame.setVisible(true);
	}

	public void setServicesService(ServicesService servicesService) {
		this.servicesService = servicesService;
	}

}
